package pl.prv.polanie.client.dialogs;

import java.util.List;

import pl.prv.polanie.client.Planner;
import pl.prv.polanie.client.dto.CSCalendarDayDTO;
import pl.prv.polanie.client.dto.CSDeclarationDTO;
import pl.prv.polanie.client.dto.CSLecturerDTO;
import pl.prv.polanie.client.dto.CSRoomDTO;
import pl.prv.polanie.client.dto.CSSubgroupDTO;
import pl.prv.polanie.client.dto.CSSubgroupTypeDTO;
import pl.prv.polanie.client.dto.CSSubjectDTO;
import pl.prv.polanie.client.dto.CSSubjectEventDTO;
import pl.prv.polanie.client.dto.CSVCalendarDayDTO;
import pl.prv.polanie.client.dto.CSVLecturerDTO;
import pl.prv.polanie.client.dto.CSVRoomDTO;
import pl.prv.polanie.client.dto.CSVSubgroupDTO;
import pl.prv.polanie.client.dto.CSVSubgroupTypeDTO;
import pl.prv.polanie.client.dto.CSVSubjectDTO;
import pl.prv.polanie.client.model.Cache;
import pl.prv.polanie.client.model.ServiceHolder;
import pl.prv.polanie.client.model.ViewDataProvider;
import pl.prv.polanie.client.panels.SchedulesList;
import pl.prv.polanie.client.panels.lists.SubjectEventsList;
import pl.prv.polanie.client.widgets.CustomDialogBox;
import pl.prv.polanie.client.widgets.SelectBoxWithObjects;
import pl.prv.polanie.client.widgets.Sorter;
import pl.prv.polanie.client.widgets.TextBoxStyled;
import pl.prv.polanie.client.widgets.schedule.Schedule;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

/**
 * 
 * @author Janusz Prokulewicz
 * Created: Apr 19, 2008
 */

public class CreateSubjectEventDialog extends CustomDialogBox {

//	private static final String STYLE__CREATE_SUBJECT_EVENT_DIALOG = "createSubjectEventDialog";
	
	
	/** Podzial, dla ktorego jest tworzony nowy/edytowany istniejacy subjectEvent.*/
	private Schedule schedule = null;
	
	
//	private SubjectEventsList subjectEventsList = null;

	
	
	/***/
	private FlexTable widgetsFT = new FlexTable();
	
	private Label subjectL = new Label("Subject");
	private SelectBoxWithObjects subjectSB = new SelectBoxWithObjects();
	
	private Label lecturerL = new Label("Lecturer");
	private SelectBoxWithObjects lecturerSB = new SelectBoxWithObjects();
	
	
	private Label subgroupL = new Label("Subgroup");
	private SelectBoxWithObjects subgroupSB = new SelectBoxWithObjects();
	
	private Label subgroupTypeL = new Label("Subgroup type");
	private SelectBoxWithObjects subgroupTypesSB = new SelectBoxWithObjects();

	private Label roomL = new Label("Room");
	private SelectBoxWithObjects roomLB = new SelectBoxWithObjects();
	
	private Label calendarDayL = new Label("Calendar Day");
	private SelectBoxWithObjects calendarDaySB = new SelectBoxWithObjects();

	private Label startTimeL = new Label("Start Time");
	private TextBox startTimeTB = new TextBoxStyled();
	
	private Label durationL = new Label("Duration");
	private TextBox durationTB = new TextBoxStyled();
	
	private Label eventCountL = new Label("event count");
	private TextBox eventCountTB = new TextBoxStyled();

	
//	private Button loadDataB = new Button("load dataa");

	private Button saveOrCreateAndCloseB = new Button("save and close");
	private Button saveOrCreateB = new Button("save/create");
	private Button closeB = new Button("close");
	
	
	private Command cmdAfterSaveButtonClicked = null;
	
	
	//referencja do dto edytowanego se
	private CSSubjectEventDTO csSubjectEventDTO = null;
	
	// jest ustawiana, jesli tworzymy subjectEventy na podstawie declaration
	private CSDeclarationDTO csDeclarationDTO = null;

	public CreateSubjectEventDialog() {
		this(null, null, null);
	}
	
	/**
	 * Dla tworzenia pojedynczego se lub edycji istniejacego (jesli csSE != null).
	 * @param schedule
	 * @param subjectEventsList
	 * @param csSE
	 */
	public CreateSubjectEventDialog(Schedule schedule, SubjectEventsList subjectEventsList,  CSSubjectEventDTO csSE) {
		this(schedule, subjectEventsList, csSE, null);
	}
	
	/**
	 * Dla tworzenia kilku se za jednym razem na podstawie declaration.
	 * @param schedule
	 * @param csD
	 */
	public CreateSubjectEventDialog(Schedule schedule, CSDeclarationDTO csD) {
		this(schedule, null, null, csD);
	}

	
	private CreateSubjectEventDialog(Schedule schedule, SubjectEventsList subjectEventsList,  CSSubjectEventDTO csSE, CSDeclarationDTO csD) {
		super(false, true);
		
//		this.subjectEventsList = subjectEventsList;
		
		this.csSubjectEventDTO = csSE;
		this.csDeclarationDTO = csD;
		this.schedule = schedule;
		
		layoutWidgets();
		setupWidgets();
		
		if (csSE != null) {
			setText("Edit subject event");
		} else {
			setText("Create new subject event");
		}
		setWidget(widgetsFT);
		
//		setStyleName(STYLE__CREATE_SUBJECT_EVENT_DIALOG);
		
		
		loadDataToWidgets();
	}



	private void setupWidgets() {
		
		
		//SUBJECT
		subjectSB.addChangeListener(new ChangeListener() {
			public void onChange(Widget sender) {
				Planner.log("CreateSubjectEventDialog, subjectLB, id => " + subjectSB.getSelectedObject());
			}
		});
		subjectSB.setWidth("370px");
		subjectSB.setItemsPanelWidth(450);
		subjectSB.setVisibleItemsCount(15);

		
		//LECTURER
		lecturerSB.addChangeListener(new ChangeListener() {
			public void onChange(Widget sender) {
				Planner.log("CreateSubjectEventDialog, lecturerSB, id => " + lecturerSB.getSelectedObject());
			}
		});
		lecturerSB.setWidth("260px");
		lecturerSB.setItemsPanelWidth(300);

		
		//SUBGROUP
		if (!isCreatingSubjectEventsBasingOnDeclaration()) {
			subgroupSB.addChangeListener(new ChangeListener() {
				public void onChange(Widget sender) {
					Planner.log("CreateSubjectEventDialog, subgroupSB, id => " + subgroupSB.getSelectedObject());
				}
			});
			subgroupSB.setWidth("200px");
			subgroupSB.setItemsPanelWidth(200);
		} else {
			subgroupTypesSB.addChangeListener(new ChangeListener() {
				public void onChange(Widget sender) {
					Planner.log("CreateSubjectEventDialog, subgroupTypesSB, id => " + subgroupTypesSB.getSelectedObject());
				}
			});
			subgroupTypesSB.setWidth("160px");
			subgroupTypesSB.setItemsPanelWidth(200);
		}
		
		
		//ROOM
		roomLB.addChangeListener(new ChangeListener() {
			public void onChange(Widget sender) {
				Planner.log("CreateSubjectEventDialog, roomLB, id => " + roomLB.getSelectedObject());
			}
		});
		roomLB.setItemsPanelWidth(200);
		roomLB.setWidth("160px");

		
		//CALENDAR DAY
//		if (!isCreatingSubjectEventsBasingOnDeclaration()) {
			calendarDaySB.addChangeListener(new ChangeListener() {
				public void onChange(Widget sender) {
					Planner.log("CreateSubjectEventDialog, calendarDayLB, id => " + calendarDaySB.getSelectedObject());
				}
			});
			calendarDaySB.setItemsPanelWidth(200);
			calendarDaySB.setWidth("160px");
			
			startTimeTB.setText("500");
			
//		}
		
		durationTB.setText("90");
		
//		subject
//		lecturer
//		subgrup
//		room
//		calendar
		
		saveOrCreateB.addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				boolean closeWindowAfterSaving = false;
				saveCSSubjectEvent(closeWindowAfterSaving);
			}
		});
		
		saveOrCreateAndCloseB.addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				boolean closeWindowAfterSaving = true;
				saveCSSubjectEvent(closeWindowAfterSaving);
			}
		});
		
		closeB.addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				hide();
			}
		});
		
		
//		loadDataB.addClickListener(new ClickListener() {
//			public void onClick(Widget sender) {
//				loadDataToWidgets();
//			}
//		});
	}

	/**
	 * Zwraca prawde, gdy tworzone sa SubjectEventy na podstawie declaration.
	 * @return
	 */
	private boolean isCreatingSubjectEventsBasingOnDeclaration() {
		return csDeclarationDTO != null;
	}



	private void layoutWidgets() {
		widgetsFT.setWidget(0, 0, subjectL);
		widgetsFT.setWidget(0, 1, subjectSB);
		
		widgetsFT.setWidget(1, 0, lecturerL);
		widgetsFT.setWidget(1, 1, lecturerSB);

		if (!isCreatingSubjectEventsBasingOnDeclaration()) {
			widgetsFT.setWidget(2, 0, subgroupL);
			widgetsFT.setWidget(2, 1, subgroupSB);
		} else {
			widgetsFT.setWidget(2, 0, subgroupTypeL);
			widgetsFT.setWidget(2, 1, subgroupTypesSB);
		}
		
		widgetsFT.setWidget(3, 0, roomL);
		widgetsFT.setWidget(3, 1, roomLB);
		
//		if (!isCreatingSubjectEventsBasingOnDeclaration()) {
			widgetsFT.setWidget(4, 0, calendarDayL);
			widgetsFT.setWidget(4, 1, calendarDaySB);

			widgetsFT.setWidget(5, 0, startTimeL);
			widgetsFT.setWidget(5, 1, startTimeTB);
//		}
		
		widgetsFT.setWidget(6, 0, durationL);
		widgetsFT.setWidget(6, 1, durationTB);

		if (isCreatingSubjectEventsBasingOnDeclaration()) {
			widgetsFT.setWidget(7, 0, eventCountL);
			widgetsFT.setWidget(7, 1, eventCountTB);
		}
		
//		widgetsFT.setWidget(8, 0, loadDataB);
		widgetsFT.setWidget(8, 1, saveOrCreateAndCloseB);
		
		widgetsFT.setWidget(9, 0, saveOrCreateB);
		widgetsFT.setWidget(9, 1, closeB);
		
	}
	
	/**
	 * TODO metoda validujaca dane
	 */
	private boolean validateEnteredData() {
		return true;
	}
	
	/**
	 * Wczytuje z cache'a dane do kontrolek. W przypadku edycji
	 * istniejacego SE ustawiane sa takze w kontrolkach odpowiednie wartosci.
	 */
	private void loadDataToWidgets() {
		
		long subjectID = -1;
		long lecturerID = -1;
		long subgroupID = -1;
		long roomID = -1;
		long calendarDayID = -1;
		
		//z csD
		long subgroupTypeID = -1;
		
//		int eventSort = 0;
		
		int startTime = 420;
		int duration = 90;
		
		
		if (csSubjectEventDTO != null) {
			
			Planner.log("CreateSubjectEventDialog.loadDataToWidgets: " + "WCZYTUJE DANE DO KONTROLEK Z SE");
			
			subjectID = csSubjectEventDTO.getSubjectID();
			lecturerID = csSubjectEventDTO.getLecturerID();
			subgroupID = csSubjectEventDTO.getSubgroupID();
			roomID = csSubjectEventDTO.getRoomID();
			calendarDayID = csSubjectEventDTO.getCalendarDayID();
			
//			eventSort = csSubjectEventDTO.getEventSort();
			
			startTime = csSubjectEventDTO.getStartTime().intValue();
			duration = csSubjectEventDTO.getDuration().intValue();
		} else if (csDeclarationDTO != null) {
			
			Planner.log("CreateSubjectEventDialog.loadDataToWidgets: " + "WCZYTUJE DANE DO KONTROLEK Z DECLARATION");
			
			subjectID = csDeclarationDTO.getSubjectID();
			subgroupTypeID = csDeclarationDTO.getSubgroupTypeID();
		}
		
		
		//subjects
		CSSubjectDTO[] subjects = Cache.getAllSubjects();
		subjectSB.clear();
		for (int i = 0; i < subjects.length; i++) {
			CSVSubjectDTO csvS = ViewDataProvider.getCSVSubject(subjects[i]);
			subjectSB.addItem(csvS.toLabel(), subjects[i]);
			
			if (subjectID == csvS.getId()) {
				subjectSB.setSelectedIndex(i);
			}
		}
		subjectSB.sortWithAlphabeticalOrder();
		
		
		//lecturers
		CSLecturerDTO[] lecturers = Cache.getAllLecturers();
		lecturerSB.clear();
		lecturerSB.addItem("-select lecturer-", new CSLecturerDTO((long)-1, "surname" , "name", (long)-1));
		for (int i = 0; i < lecturers.length; i++) {
			CSVLecturerDTO csvL = ViewDataProvider.getCSVLecturer(lecturers[i]);
			lecturerSB.addItem(csvL.toLabel(), lecturers[i]);
			
			if (lecturerID == csvL.getId()) {
				lecturerSB.setSelectedIndex(i+1);
			}
		}
		lecturerSB.sortWithAlphabeticalOrder();
		
	
		
		
		
		if (!isCreatingSubjectEventsBasingOnDeclaration()) {
			
			//wczytanie danych do kontrolki subgroupSB
			
			long groupID = schedule.getFilterPropertyGroupID();
			
			CSSubgroupDTO[] subgroups = Cache.getSubgroupsByGroupID(groupID);
			
			Sorter sorter = new Sorter();
			for (int i = 0; i < subgroups.length; i++) {
				sorter.addItem(subgroups[i].getName(), subgroups[i]);
			}
			sorter.sortWithAlphabeticalOrder();
			List<Object> objects = sorter.getListWithObjects();
			subgroups = objects.toArray(subgroups);
			
			subgroupSB.clear();
			//subgroupLB.addItem("select subgroup", new CSSubgroupDTO((long)-1, (long)-1, (long)-1, "name", new Integer(-1)));
			for (int i = 0; i < subgroups.length; i++) {
				CSVSubgroupDTO csvS = ViewDataProvider.getCSVSubgroup(subgroups[i]);
				subgroupSB.addItem(csvS.toLabelShort(), subgroups[i]);
				
				if (subgroupID == csvS.getId()) {
					subgroupSB.setSelectedIndex(i);
				}
			}
			
		} else {
			
			//wczytanie danych do kontrolki subgroupTypesSB
			CSSubgroupTypeDTO[] subgroupTypes = Cache.getAllSubgroupTypes();
			
			Sorter sorter = new Sorter();
			for (int i = 0; i < subgroupTypes.length; i++) {
				sorter.addItem(subgroupTypes[i].getName(), subgroupTypes[i]);
			}
			sorter.sortWithAlphabeticalOrder();
			List<Object> objects = sorter.getListWithObjects();
			subgroupTypes = objects.toArray(subgroupTypes);
			
			subgroupTypesSB.clear();
			//subgroupLB.addItem("select subgroup", new CSSubgroupDTO((long)-1, (long)-1, (long)-1, "name", new Integer(-1)));
			for (int i = 0; i < subgroupTypes.length; i++) {
				CSVSubgroupTypeDTO csvST = ViewDataProvider.getCSVSubgroupType(subgroupTypes[i]);
				subgroupTypesSB.addItem(csvST.getName(), subgroupTypes[i]);
				
				if (subgroupTypeID == csvST.getId()) {
					subgroupTypesSB.setSelectedIndex(i);
				}
			}
			
		}

		
		
		CSRoomDTO[] rooms = Cache.getAllRooms();
		roomLB.clear();
		roomLB.addItem("-select room-", new CSRoomDTO((long)-1, "name", new Long(-1), (long)-1, (long) -1 ));
		for (int i = 0; i < rooms.length; i++) {
			CSVRoomDTO csvR = ViewDataProvider.getCSVRoom(rooms[i]);
			roomLB.addItem(csvR.toLabel(), rooms[i]);
			
			if (roomID == csvR.getId()) {
				roomLB.setSelectedIndex(i+1);
			}
		}
		roomLB.sortWithAlphabeticalOrder();
		

//		if (!isCreatingSubjectEventsBasingOnDeclaration()) {
			CSCalendarDayDTO[] calendarDays = Cache.getAllCalendarDays();
			
			Sorter sorter = new Sorter();
			for (int i = 0; i < calendarDays.length; i++) {
				sorter.addItem(new Long(calendarDays[i].getDisplayOrder()), calendarDays[i]);
			}
			sorter.sortWithAlphabeticalOrder();
			List<Object> objects = sorter.getListWithObjects();
			calendarDays = objects.toArray(calendarDays);
			
			calendarDaySB.clear();
			calendarDaySB.addItem("-not assigned-", null);
			for (int i = 0; i < calendarDays.length; i++) {
				CSVCalendarDayDTO csvCD = ViewDataProvider.getCSVCalendarDay(calendarDays[i]);
				calendarDaySB.addItem(csvCD.toLabel(), calendarDays[i]);
				if (calendarDayID == csvCD.getId()) {
					calendarDaySB.setSelectedIndex(i+1);
				}
			}
			
			startTimeTB.setText("" + startTime);
//		}
		
		durationTB.setText("" + duration);
		eventCountTB.setText("1");
	}

	/**
	 * Zapisuje/aktualizuje subjectEventa. 
	 * @param closeWindowAfterSaving
	 */
	private void saveCSSubjectEvent(final boolean closeWindowAfterSaving) {
		if (validateEnteredData()) {
			
			if (!isCreatingSubjectEventsBasingOnDeclaration()) {
				
				final CSSubjectEventDTO se = new CSSubjectEventDTO();
				
				//w przypadku edycji SE
				if (csSubjectEventDTO != null) {
					se.setId(csSubjectEventDTO.getId());
					se.setEventSort(csSubjectEventDTO.getEventSort());
				} else {
					se.setEventSort(0);
				}
				
				
				long subjectID = ((CSSubjectDTO)subjectSB.getSelectedObject()).getId();
				se.setSubjectID(subjectID);
				
				long lecturerID = -1;
				CSLecturerDTO lect = ((CSLecturerDTO)lecturerSB.getSelectedObject());
				if (lect != null) {
					lecturerID = lect.getId();
				}
				se.setLecturerID(lecturerID);
				
				long subgroupID = ((CSSubgroupDTO)subgroupSB.getSelectedObject()).getId(); 
				se.setSubgroupID(subgroupID);
				
				
				long roomID = -1;
				CSRoomDTO room = ((CSRoomDTO)roomLB.getSelectedObject());
				if (room != null) {
					roomID = room.getId();
				}
				se.setRoomID(roomID);
				
				long calendarDayID = -1;
				CSCalendarDayDTO cd = ((CSCalendarDayDTO)calendarDaySB.getSelectedObject());
				if (cd != null) {
					calendarDayID = cd.getId();
				}
				se.setCalendarDayID(calendarDayID);
				
				
				//usuniecie sujectEventa z widoku schedule gdy calendarDayID == -1
				if (calendarDayID == -1) {
					schedule.removeCSSubjectEvent(se);
				}
				
				
				se.setStartTime(new Integer(startTimeTB.getText()));
				se.setDuration(new Integer(durationTB.getText()));
				
				
				AsyncCallback<Long> callback = new AsyncCallback<Long>() {
					public void onFailure(Throwable caught) {
						Planner.log("CreateSubjectEventDialog.saveSubjectEvent() FAILURE");
					}
					public void onSuccess(Long res) {
						Planner.log("CreateSubjectEventDialog.saveSubjectEvent() SUCCESS -> zwrocone ID = " + res);
						
						se.setId(res.longValue());
						
						if (schedule != null) {
							schedule.addCSSubjectEvent(se);
						}
						if (closeWindowAfterSaving) {
							hide();
						}
						
						Cache.saveOrUpdateCSSubjectEvent(se);
						SchedulesList.generateReports();
						
					}
				};
				
				ServiceHolder.get().saveCSSubjectEvent(se, callback);
				
				
				
			} else {
				
				Planner.log("CreateSubjectEventDialog.saveCSSubjectEvent: "
						+ "KILKA SUBJECT EVENTOW!!");
				//////zapis kilku CSSubjectEvent
				
				//subgroupTypeID => ile ma zostac stworzonych SE
				int eventCount = new Integer(eventCountTB.getText()).intValue();
				long subgroupTypeID = ((CSSubgroupTypeDTO)subgroupTypesSB.getSelectedObject()).getId();
				int subgroupsCount = Cache.getSubgroupsCountByGroupIDAndSubgroupTypeID(schedule.getFilterPropertyGroupID(), subgroupTypeID);
				
				Planner.log("CreateSubjectEventDialog.saveCSSubjectEvent: "
						+ " SUBGROUPS COUNT  znalazlem podgrup o podanym typie: " + subgroupsCount);
				
				final int seCount = subgroupsCount * eventCount;
					
				final CSSubjectEventDTO[] ses = new CSSubjectEventDTO[seCount];
				

//				CSSubjectEventDTO se = ses[i];
				
				//ODCZYTANIE DANYCH Z DANYCH
				long subjectID = ((CSSubjectDTO)subjectSB.getSelectedObject()).getId();
				
				long lecturerID = -1;
				CSLecturerDTO lect = ((CSLecturerDTO)lecturerSB.getSelectedObject());
				if (lect != null) {
					lecturerID = lect.getId();
				}
				
				long roomID = -1;
				CSRoomDTO room = ((CSRoomDTO)roomLB.getSelectedObject());
				if (room != null) {
					roomID = room.getId();
				}
				
				long calendarDayID = -1;
				CSCalendarDayDTO cd = ((CSCalendarDayDTO)calendarDaySB.getSelectedObject());
				if (cd != null) {
					calendarDayID = cd.getId();
				}
				
				int duration = new Integer(durationTB.getText()).intValue();
				
				long groupID = schedule.getFilterPropertyGroupID();
				Long[] subgroupsIDs = Cache.getSubgroupsIDsByGroupIDAndSubgroupTypeID(groupID, subgroupTypeID);

				
				for (int i = 0; i < eventCount; i++) {
					for (int j = 0; j < subgroupsCount; j++) {
						
						CSSubjectEventDTO se = new CSSubjectEventDTO();
						long subgroupID = subgroupsIDs[j];
						se.setSubjectID(subjectID);
						se.setLecturerID(lecturerID);
						se.setSubgroupID(subgroupID);
						se.setRoomID(roomID);
						se.setCalendarDayID(calendarDayID);
						se.setStartTime(420);
						se.setDuration(duration);
						
						ses[i*subgroupsCount + j] = se; 
					}
				}
				
				
				
				AsyncCallback<long[]> callback = new AsyncCallback<long[]>() {
					public void onFailure(Throwable caught) {
						Planner.log("CreateSubjectEventDialog.saveSubjectEvent() FAILURE");
					}
					public void onSuccess(long[] res) {
						Planner.log("CreateSubjectEventDialog.saveSubjectEvent() SUCCESS -> zwrocone ID = " + res);
						
						
						for (int i = 0; i < seCount; i++) {
							Planner.log("CreateSubjectEventDialog.saveSubjectEvent() SUCCESS id[" + i +"] => " + res[i]);
							ses[i].setId(res[i]);
							
							if (schedule != null) {
								schedule.addCSSubjectEvent(ses[i]);
							}
						}
						
						
						if (closeWindowAfterSaving) {
							hide();
						}

						
						for (int i = 0; i < ses.length; i++) {
							Cache.saveOrUpdateCSSubjectEvent(ses[i]);
						}
						SchedulesList.generateReports();
						
					}
				};
				
				ServiceHolder.get().saveCSSubjectEvents(ses, callback);
				
				
				
				
				
				
			}
			
		}
	}


	public void setCmdAfterSaveButtonClicked(Command cmdAfterSaveButtonClicked) {
		this.cmdAfterSaveButtonClicked = cmdAfterSaveButtonClicked;
	}


	public void setCsSubjectEventDTO(CSSubjectEventDTO csSubjectEventDTO) {
		this.csSubjectEventDTO = csSubjectEventDTO;
	}

	
}
